package com.itaming.lycheeframework.redis.serializer;

import com.fasterxml.jackson.core.json.JsonReadFeature;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;

import java.util.Map;

/**
 * 序列化器工厂
 *
 * @author A.Ming
 */
public class SerializerFactory {

    /**
     * 序列化器
     */
    private static final Map<SerializationMode, RedisSerializer<?>> SERIALIZERS = Map.of(
        SerializationMode.PROTOSTUFF, createProtostuffSerializer(),
        SerializationMode.JACKSON, createJacksonSerializer(),
        SerializationMode.JDK, createJdkSerializer()
    );

    /**
     * 获取key序列化器
     *
     * @return 序列化器
     */
    public static RedisSerializer<?> getKeySerializer() {
        return RedisSerializer.string();
    }

    /**
     * 获取value序列化器
     *
     * @return 序列化器
     */
    public static RedisSerializer<?> getValueSerializer(SerializationMode mode) {
        RedisSerializer<?> serializer = SERIALIZERS.get(mode);
        if (serializer == null) {
            throw new IllegalArgumentException("Unsupported serialization mode: " + mode);
        }

        return serializer;
    }

    /**
     * 创建<code>Protostuff</code>序列化器
     *
     * @return 序列化器
     */
    private static RedisSerializer<?> createProtostuffSerializer() {
        return new ProtostuffRedisSerializer();
    }

    /**
     * 创建<code>Jackson</code>序列化器
     *
     * @return 序列化器
     */
    private static RedisSerializer<?> createJacksonSerializer() {
        return new GenericJackson2JsonRedisSerializer()
            .configure(objectMapper -> objectMapper
                // 注册Java8时间序列化模块
                .registerModule(new JavaTimeModule())
                // 禁止时间序列化为时间戳
                .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
                // 忽略失败：空对象（没有可序列化的字段）
                .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
                // 忽略失败：反序列化时属性不存在(JSON中存在但Java类中不存在）
                .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
                // 允许包含非引号控制字符（值小于32的ASCII字符：包含制表符和换行符）
                .enable(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature())
                // 允许反斜杠转义任何字符
                .enable(JsonReadFeature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER.mappedFeature())
                // 允许使用单引号包裹字段名
                .enable(JsonReadFeature.ALLOW_SINGLE_QUOTES.mappedFeature())
            );
    }

    /**
     * 创建<code>JDK</code>序列化器
     *
     * @return 序列化器
     */
    private static RedisSerializer<?> createJdkSerializer() {
        return RedisSerializer.java(SerializerFactory.class.getClassLoader());
    }

}
